#include "FrameProducerConsumer.h"

#include <QtCore/QCoreApplication>
#include <qtcore/QQueue>
#include <qtcore/QSemaphore>
#include <QtCore/QEventLoop>
#include <QtCore/QMutexLocker>
#include <QtGui/QMouseEvent>
#include <QtCore/QPoint>
#include <QtCore/qtimer.h>
//#include <crtdbg.h>
#ifdef WIN32
#include <direct.h>
#endif

#include "GraphTools.h"
#include "FrameMaker.h"
#include <string>


namespace DDAGui{
    const int MAXFRAMESNUM = 3;
    DISPLAYMODE playMode = DISPLAY_ACCUMULATION_DISPLACEMENT;

    class SynchronizationQueue
    {
    public:
        void enqueue(FrameData& frameData){
            _lock.lock();
            _queue.enqueue(frameData);
            _lock.unlock();
        }
        FrameData dequeue(){
            QMutexLocker locker(&_lock);
            return _queue.dequeue();
        }
        FrameData& head(){
            QMutexLocker locker(&_lock);
            return _queue.head();
        }

        int size(){
            QMutexLocker locker(&_lock);
            return _queue.size();
        }
        void clear(){
            QMutexLocker locker(&_lock);
            _queue.clear();
        }


    private:
        QQueue<FrameData> _queue;
        QMutex _lock;

    }frameQueue;
}


using namespace DDAGui;
using namespace std;
//////////////////////////////////////
////  producer
//////////////////////////////////////
void FrameProducer::_realProduce1Frame()
{
    if(_dataTaker->hasNextFrame())
    {
        if(!_lock.tryLock() ) // wait for 0.5 second to acquire free resource
            return;
        if( frameQueue.size()>=MAXFRAMESNUM)
        {
            _lock.unlock();
            return;
        }

#ifdef DEBUGPRODUCER
        msg("get new free resource.\n");
#endif
        try
        {
            frameQueue.enqueue(_dataTaker->getNextGraph());
        }
        catch (std::exception e)
        {
            throw e;
        }
#ifdef DEBUGPRODUCER
        msg("one frame parsed done.\n");
#endif
        _lock.unlock();
        emit oneFrameProduced();

    }
    else
        emit noMoreFrames();
}

void FrameProducer::produceFrames()
{
    _realProduce1Frame();
    //    if( frameQueue.size()<MAXFRAMESNUM)  // make sure more than frames are available
    //        _realProduce1Frame();
}

void FrameProducer::produce1Frame()
{
	if(!_lock.tryLock() ) // wait for 0.5 second to acquire free resource
		return;
	int tmp = frameQueue.size();
	if( frameQueue.size()!=0)
	{
		frameQueue.clear();
	}
	_lock.unlock();


    _realProduce1Frame();
	msg("+++++++++++++++1 frame produced==========\n");
}

void FrameProducer::setStartFrameIndex(int frameIndex)
{
#ifdef DEBUGPRODUCER
    char tmpStr[200];
    sprintf(tmpStr , "set start frame %d\n" , frameIndex);
    msg(tmpStr);
#endif

    _lock.lock();
    _dataTaker->setCurrentFrameIdx(frameIndex);
    _lock.unlock();
}



//////////////////////////////////////
////  consumer
//////////////////////////////////////

bool FrameConsumer::ifContinuePlay()
{
    return _ifContinuePlay && !_ifProduceDone;
}

void FrameConsumer::pausePlay()
{
#ifdef DEBUGCONSUMER
    msg("================pause play=====================\n");
#endif
    _ifContinuePlay = false;
}


void FrameConsumer::acceptPlayEnd()
{
#ifdef DEBUGCONSUMER
    msg("================no more frames.=====================\n");
#endif
    _ifProduceDone = true;
}

void FrameConsumer::stopPlay()
{
#ifdef DEBUGCONSUMER
    msg("================stop play=====================\n");
#endif
    _ifContinuePlay = false;
    emit frameIndexChanged(0);
}

void FrameConsumer::startPlay()
{
#ifdef DEBUGCONSUMER
    msg("================start play.=====================\n");
#endif
    _ifProduceDone = false;
    _ifContinuePlay = true;
    emit requireFrames();
}


void FrameConsumer::display1Frame(int frameIdx)
{
    //char tmpStr[200];
    //sprintf(tmpStr , "current frame %d\n" , frameIdx);
    //msg(tmpStr);

    _ifContinuePlay = false;

	int tmp = frameQueue.size();
	if( frameQueue.size()!=0)
	{
		frameQueue.clear();
	}


    emit setStartFrameIndex(frameIdx);
    emit require1Frame();
}

void FrameConsumer::displayFrames()
{
    msg("start display\n");
    if(!_lock.tryLock() )
        return;

//     if(frameQueue.size()<1)
//     {
//         _lock.unlock();
//         return;
//     }

    assert(frameQueue.size()>0);
    //     Sleep(TIMEINTERVAL);

    DISPLAYMODE tmpMode = playMode;

    int FrameIdx = frameQueue.head().frameNo;
    _frameMaker->updateGraph(frameQueue.dequeue() , playMode);
    emit frameIndexChanged(FrameIdx);

    //     if(_ifContinuePlay){
    //         if(!_ifProduceDone)
    //             emit requireFrames();
    //     }
    //     else
    //         frameQueue.clear();
    // 
    //     if(!_ifProduceDone)   // player already finished, now play the last rest frames.
    //     {
    //         int size = frameQueue.size();
    //         while(size--)
    //         {
    //             int FrameIdx = frameQueue.head().frameNo;
    //             _frameMaker->updateGraph(frameQueue.dequeue() , playMode);
    //             emit frameIndexChanged(FrameIdx);
    //         }
    //     }
    _lock.unlock();
}
